home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / javax / swing / AppContext.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  8.9 KB  |  242 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)AppContext.java    1.2 98/08/26
  3.  *
  4.  * Copyright 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package javax.swing;
  16.  
  17. import java.util.Hashtable;
  18. import java.util.Enumeration;
  19.  
  20. /**
  21.  * The AppContext is a per-SecurityContext table which stores application
  22.  * service instances.  (If you are not writing an application service, or
  23.  * don't know what one is, please do not use this class.)  The AppContext
  24.  * allows applet access to what would otherwise be potentially dangerous
  25.  * services, such as the ability to peek at EventQueues or change the
  26.  * look-and-feel of a Swing application.<p>
  27.  *
  28.  * Most application services use a singleton object to provide their
  29.  * services, either as a default (such as getSystemEventQueue or 
  30.  * getDefaultToolkit) or as static methods with class data (System).
  31.  * The AppContext works with the former method by extending the concept
  32.  * of "default" to be SecurityContext-specific.  Application services
  33.  * lookup their singleton in the AppContext; if it hasn't been created,
  34.  * the service creates the singleton and stores it in the AppContext.<p>
  35.  *
  36.  * For example, here we have a Foo service, with its pre-AppContext
  37.  * code:<p>
  38.  * <code><pre>
  39.  *    public class Foo {
  40.  *        private static Foo defaultFoo = new Foo();
  41.  *
  42.  *        public static Foo getDefaultFoo() {
  43.  *            return defaultFoo;
  44.  *        }
  45.  *
  46.  *    ... Foo service methods
  47.  *    }</pre></code><p>
  48.  *
  49.  * The problem with the above is that the Foo service is global in scope,
  50.  * so that applets and other untrusted code can execute methods on the
  51.  * single, shared Foo instance.  The Foo service therefore either needs
  52.  * to block its use by untrusted code using a SecurityManager test, or
  53.  * restrict its capabilities so that it doesn't matter if untrusted code
  54.  * executes it.<p>
  55.  *
  56.  * Here's the Foo class written to use the AppContext:<p>
  57.  * <code><pre>
  58.  *    public class Foo {
  59.  *        public static Foo getDefaultFoo() {
  60.  *            Foo foo = (Foo)AppContext.getAppContext().get(Foo.class);
  61.  *            if (foo == null) {
  62.  *                foo = new Foo();
  63.  *                getAppContext().put(Foo.class, foo);
  64.  *            }
  65.  *            return foo;
  66.  *        }
  67.  *
  68.  *    ... Foo service methods
  69.  *    }</pre></code><p>
  70.  *
  71.  * Since a separate AppContext exists for each SecurityContext, trusted
  72.  * and untrusted code have access to different Foo instances.  This allows
  73.  * untrusted code access to "system-wide" services -- the service remains
  74.  * within the security "sandbox".  For example, say a malicious applet 
  75.  * wants to peek all of the key events on the EventQueue to listen for
  76.  * passwords; if separate EventQueues are used for each SecurityContext
  77.  * using AppContexts, the only key events that applet will be able to
  78.  * listen to are its own.  A more reasonable applet request would be to
  79.  * change the Swing default look-and-feel; with that default stored in
  80.  * an AppContext, the applet's look-and-feel will change without 
  81.  * disrupting other applets or potentially the browser itself.<p>
  82.  *
  83.  * Because the AppContext is a facility for safely extending application
  84.  * service support to applets, none of its methods may be blocked by a
  85.  * a SecurityManager check in a valid Java implementation.  Applets may
  86.  * therefore safely invoke any of its methods without worry of being 
  87.  * blocked.
  88.  *
  89.  * @author  Thomas Ball
  90.  * @version 1.2 08/26/98
  91.  */
  92. final class AppContext {
  93.  
  94.     /* Since the contents of an AppContext are unique to each Java 
  95.      * session, this class should never be serialized. */
  96.  
  97.     /* A map of AppContexts, referenced by SecurityContext.
  98.      * If the map is null then only one context, the systemAppContext,
  99.      * has been referenced so far.
  100.      */
  101.     private static Hashtable security2appContexts = null;
  102.  
  103.     // A handle to be used when the SecurityContext is null.
  104.     private static Object nullSecurityContext = new Object();
  105.     private static AppContext systemAppContext = 
  106.         new AppContext(nullSecurityContext);
  107.  
  108.     /*
  109.      * The hashtable associated with this AppContext.  A private delegate
  110.      * is used instead of subclassing Hashtable so as to avoid all of
  111.      * Hashtable's potentially risky methods, such as clear(), elements(),
  112.      * putAll(), etc.  (It probably doesn't need to be final since the
  113.      * class is, but I don't trust the compiler to be that smart.)
  114.      */
  115.     private final Hashtable table;
  116.  
  117.     /* The last key-pair cache -- comparing to this before doing a 
  118.      * lookup in the table can save some time, at the small cost of
  119.      * one additional pointer comparison. 
  120.      */
  121.     private static Object lastKey;
  122.     private static Object lastValue;
  123.  
  124.     private AppContext(Object securityContext) {
  125.         table = new Hashtable(2);
  126.         if (securityContext != nullSecurityContext) {
  127.             if (security2appContexts == null) {
  128.                 security2appContexts = new Hashtable(2, 0.2f);
  129.             }
  130.             security2appContexts.put(securityContext, this);
  131.         }
  132.     }
  133.  
  134.     /**
  135.      * Returns the appropriate AppContext for the caller, 
  136.      * as determined by its SecurityContext.  
  137.      *
  138.      * @returns the AppContext for the caller.
  139.      * @see     java.lang.SecurityManager#getSecurityContext
  140.      * @since   JDK1.2
  141.      */
  142.     public static AppContext getAppContext() {
  143.         // Get security context, if any.
  144.  
  145.         Object securityContext = nullSecurityContext;
  146. /*
  147.  Commenting out until we can reliably compute AppContexts
  148.  
  149.         SecurityManager sm = System.getSecurityManager();
  150.         if (sm != null) {
  151.             Object context = sm.getSecurityContext();
  152.             if (context != null) {
  153.                 securityContext = context;
  154.             }
  155.         }
  156.         */
  157.  
  158.         // Map security context to AppContext.
  159.         if (securityContext == nullSecurityContext) {
  160.             return systemAppContext;
  161.         }
  162.         AppContext appContext = 
  163.             (AppContext)security2appContexts.get(securityContext);
  164.         if (appContext == null) {
  165.             appContext = new AppContext(securityContext);
  166.             security2appContexts.put(securityContext, appContext);
  167.         }
  168.         return appContext;
  169.     }
  170.  
  171.     /**
  172.      * Returns the value to which the specified key is mapped in this context.
  173.      *
  174.      * @param   key   a key in the AppContext.
  175.      * @return  the value to which the key is mapped in this AppContext;
  176.      *          <code>null</code> if the key is not mapped to any value.
  177.      * @see     #put(Object, Object)
  178.      * @since   JDK1.2
  179.      */
  180.     public synchronized Object get(Object key) {
  181.         if (key != lastKey || lastValue == null) {
  182.             lastValue = table.get(key);
  183.             lastKey = key;
  184.         }
  185.         return lastValue;
  186.     }
  187.  
  188.     /**
  189.      * Maps the specified <code>key</code> to the specified 
  190.      * <code>value</code> in this AppContext.  Neither the key nor the 
  191.      * value can be <code>null</code>.
  192.      * <p>
  193.      * The value can be retrieved by calling the <code>get</code> method 
  194.      * with a key that is equal to the original key. 
  195.      *
  196.      * @param      key     the AppContext key.
  197.      * @param      value   the value.
  198.      * @return     the previous value of the specified key in this 
  199.      *             AppContext, or <code>null</code> if it did not have one.
  200.      * @exception  NullPointerException  if the key or value is
  201.      *               <code>null</code>.
  202.      * @see     #get(Object)
  203.      * @since   JDK1.2
  204.      */
  205.     public synchronized Object put(Object key, Object value) {
  206.         return table.put(key, value);
  207.     }
  208.  
  209.     /**
  210.      * Removes the key (and its corresponding value) from this 
  211.      * AppContext. This method does nothing if the key is not in the
  212.      * AppContext.
  213.      *
  214.      * @param   key   the key that needs to be removed.
  215.      * @return  the value to which the key had been mapped in this AppContext,
  216.      *          or <code>null</code> if the key did not have a mapping.
  217.      * @since   JDK1.2
  218.      */
  219.     public synchronized Object remove(Object key) {
  220.         return table.remove(key);
  221.     }
  222.  
  223.     /**
  224.      * Returns a string representation of this AppContext.
  225.      * @since   JDK1.2
  226.      */
  227.     public String toString() {
  228.         Object securityContext = nullSecurityContext;
  229.         SecurityManager sm = System.getSecurityManager();
  230.         if (sm != null) {
  231.             Object context = 
  232.                 System.getSecurityManager().getSecurityContext();
  233.             if (context != null) {
  234.                 securityContext = context;
  235.             }
  236.         }
  237.         String contextName = (securityContext.equals(nullSecurityContext) ?
  238.             "null" : securityContext.toString());
  239.     return getClass().getName() + "[SecurityContext=" + contextName + "]";
  240.     }
  241. }
  242.